package com.bdbit.ChargingStation.services;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.bdbit.ChargingStation.alipay.Config;

import com.bdbit.ChargingStation.wx.WxConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;  // 添加这行导入
import java.util.Map;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.api.internal.util.AlipaySignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.extern.slf4j.Slf4j;

import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;

/**
 * 支付宝支付服务
 *
 * @author sheng
 */
@Service
//@Slf4j
public class AliPayService {
    private final Gson gson = new GsonBuilder().serializeNulls().create();
    private static final Logger log = LoggerFactory.getLogger(AliPayService.class);

    /**
     * 创建支付表单212
     * @param orderId 订单号
     * @param amount 金额
     * @return 支付表单HTML
     */
    public String createPaymentForm(String orderId, BigDecimal amount) {
        try {
            return aliWappay(orderId, amount.toString());
        } catch (AlipayApiException e) {
            log.error("创建支付宝支付表单失败: orderId={}, amount={}", orderId, amount, e);
            return null;
        }
    }

    /**
     * 验证支付宝回调签名212
     * @param params 回调参数
     * @return 是否验证通过
     */
    public boolean verifySignature(Map<String, String> params) {
        try {
            // 获取支付宝公钥
            String alipayPublicKey = Config.getInstance().getAlipayPublicKey();
            
            // 验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(
                params, 
                alipayPublicKey, 
                "UTF-8", 
                "RSA2"
            );
            
            if (signVerified) {
                log.info("支付宝回调签名验证成功");
                return true;
            } else {
                log.warn("支付宝回调签名验证失败");
                return false;
            }
        } catch (Exception e) {
            log.error("支付宝回调签名验证异常", e);
            return false;
        }
    }

    /**
     * 创建订单
     * <a href="https://opendocs.alipay.com/open/02ivbs?scene=21">手机网站支付接口2.0接口</a>
     */
    public String aliWappay(String outTradeNo, String totalAmount) throws AlipayApiException {
        try {
            log.info("开始创建支付宝支付: outTradeNo={}, totalAmount={}", outTradeNo, totalAmount);
            
            // 验证金额格式和范围
            BigDecimal amount = new BigDecimal(totalAmount);
            if (amount.compareTo(new BigDecimal("0.01")) < 0) {
                throw new AlipayApiException("支付金额不能小于0.01元");
            }
            if (amount.compareTo(new BigDecimal("100000")) > 0) {
                throw new AlipayApiException("支付金额不能超过100000元");
            }
            
            // 格式化金额，确保最多两位小数
            String formattedAmount = amount.setScale(2, RoundingMode.HALF_UP).toString();
            log.info("格式化后的金额: {}", formattedAmount);
            
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(Config.getInstance().getAlipayConfig());
            
            // 构造请求参数
            AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
            
            // 构建标准的JSON格式，确保没有多余的逗号或格式错误
            JSONObject bizContentObj = new JSONObject();
            bizContentObj.put("out_trade_no", outTradeNo);
            bizContentObj.put("total_amount", formattedAmount);
            bizContentObj.put("subject", "充电桩服务");
            bizContentObj.put("product_code", "QUICK_WAP_WAY");
            bizContentObj.put("timeout_express", "15m");  // 减少超时时间到15分钟
            
            String bizContent = bizContentObj.toJSONString();
            request.setBizContent(bizContent);
            
            // 设置返回URL和通知URL
            request.setReturnUrl("https://tiaozhuan.siji.pro/pages/SelectPackage/index");
            request.setNotifyUrl("https://tiaozhuan.siji.pro/api/order/alipayNotify");  // 添加异步通知URL



            log.info("请求参数: bizContent={}", bizContent);
            
            // 使用GET方式（沙箱环境更兼容）
            AlipayTradeWapPayResponse response = alipayClient.pageExecute(request, "GET");
            
            String pageRedirectionData = response.getBody();
            
            if (response.isSuccess()) {
                log.info("支付宝支付表单创建成功: orderId={}, amount={}", outTradeNo, formattedAmount);
                return pageRedirectionData;
            } else {
                log.error("支付宝支付表单创建失败: code={}, msg={}, subCode={}, subMsg={}",
                        response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
                throw new AlipayApiException("支付表单创建失败: " + response.getMsg());
            }
        } catch (NumberFormatException e) {
            log.error("金额格式错误: {}", totalAmount, e);
            throw new AlipayApiException("金额格式错误: " + totalAmount);
        } catch (Exception e) {
            log.error("支付宝支付异常: ", e);
            throw new AlipayApiException("支付宝支付创建失败: " + e.getMessage());
        }
    }

    /**
     * 支付宝退款
     * @param orderId 订单号
     * @param refundAmount 退款金额（元为单位111）
     * @return 退款是否成功
     */
    public boolean refund(String orderId, BigDecimal refundAmount) throws AlipayApiException {
        try {
            // 验证退款金额的合理性
            if (refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
                log.error("退款金额无效: orderId={}, refundAmount={}", orderId, refundAmount);
                return false;
            }
            
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(Config.getInstance().getAlipayConfig());
            
            // 创建退款请求对象
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            
            // 构建退款请求参数
            JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderId);
            // 确保退款金额格式正确（保留2位小数）2121
            bizContent.put("refund_amount", refundAmount.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            bizContent.put("refund_reason", "充电桩服务中断退款");
            bizContent.put("out_request_no", "refund_" + orderId + "_" + System.currentTimeMillis());
            
            request.setBizContent(bizContent.toString());
            
            log.info("支付宝退款请求: orderId={}, refundAmount={}元, bizContent={}", 
                    orderId, refundAmount, bizContent.toString());
            
            // 发送退款请求
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            
            // 检查退款结果
            if (response.isSuccess()) {
                // 退款成功
                log.info("支付宝退款成功: orderId={}, refundAmount={}元, response={}", 
                        orderId, refundAmount, response.getBody());
                return true;
            } else {
                // 退款失败
                log.error("支付宝退款失败: orderId={}, refundAmount={}元, code={}, msg={}, subCode={}, subMsg={}", 
                        orderId, refundAmount, response.getCode(), response.getMsg(), 
                        response.getSubCode(), response.getSubMsg());
                return false;
            }
        } catch (AlipayApiException e) {
            log.error("支付宝退款API异常: orderId={}, refundAmount={}元", orderId, refundAmount, e);
            throw e;
        } catch (Exception e) {
            log.error("支付宝退款异常: orderId={}, refundAmount={}元", orderId, refundAmount, e);
            return false;
        }
    }

    /**
     * 通过授权码获取支付宝用户ID
     * @param authCode 授权码
     * @return 用户ID
     */
    public String getUserId(String authCode) {
        try {
            // 添加输入参数日志
            log.info("开始获取支付宝用户ID，授权码: {}", authCode);
            
            // 验证授权码格式 - 沙箱环境特殊处理
            if (authCode == null || authCode.trim().isEmpty()) {
                log.error("授权码为空");
                return null;
            }
            
            // 沙箱环境授权码检查
            if (authCode.startsWith("test_")) {
                log.info("检测到测试授权码，直接使用作为用户标识: {}", authCode);
                return authCode;
            }
            
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(Config.getInstance().getAlipayConfig());
            
            // 创建获取访问令牌的请求
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            request.setGrantType("authorization_code");
            request.setCode(authCode.trim());
            
            // 添加请求参数日志
            log.info("请求参数 - GrantType: {}, Code: {}", request.getGrantType(), request.getCode());
            
            // 执行请求
            AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
            
            // 详细的响应日志
            log.info("支付宝API响应 - Success: {}, Code: {}, Msg: {}, SubCode: {}, SubMsg: {}", 
                    response.isSuccess(), response.getCode(), response.getMsg(), 
                    response.getSubCode(), response.getSubMsg());
            
            if (response.isSuccess()) {
                String alipayUserId = response.getAlipayUserId();
                
                // 如果alipayUserId为空，直接返回授权码作为userid
                if (alipayUserId == null || alipayUserId.trim().isEmpty()) {
                    log.warn("支付宝用户ID为空，直接使用授权码作为用户标识");
                    return authCode;
                }
                
                return alipayUserId;
            } else {
                // 特殊错误码处理
                if ("isv.code-invalid".equals(response.getSubCode())) {
                    log.warn("沙箱环境授权码无效，这是正常现象，使用授权码作为用户标识: {}", authCode);
                    return authCode;
                }
                
                log.error("支付宝授权失败 - 错误码: {}, 错误信息: {}, 子错误码: {}, 子错误信息: {}", 
                        response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
                
                // 授权失败时也返回授权码作为fallback
                log.warn("支付宝授权失败，使用授权码作为fallback用户标识");
                return authCode;
            }
        } catch (Exception e) {
            log.error("支付宝授权异常 - 授权码: {}", authCode, e);
            // 异常时也返回授权码作为fallback
            log.warn("支付宝授权异常，使用授权码作为fallback用户标识");
            return authCode;
        }
    }
}
